//
// Created by YH31 on 2021/6/9.
//

#include "crc_8.h"
#include "stdio.h"
/**
 * 获得data 数据为1的最高位的位置
 * @param data
 * @return
 */
uint8_t getMbsBitIndex(uint8_t data){
    uint8_t index;
    for (index=7;  index>0 ; index--) {
        if((0x01<<index)&data){
            return index;
        }
    }

}
/**
 * 通过生成式
 *          G的16进制表示法 0x07
 *          对应的多项式为 x^8+x^2+x+1===>0x107==>对应的二进制是==>100000111
 *          G的真实值=0x107
 *          r=8
 *          m=data
 *          NM:二进制的data在后面+r个0
 *
 * 原理：将data<<8 获得NM
 *      NM/G 的余数即data的校验码，这里的除法为多项式除法，且取余的减法是模2运算，即二进制的异或
 *      通过G多项式对应的二进制为1的最高位与NM对应的二进制为1的最高位对齐进行异或运算获得的结果temp_value
 *      如果temp_value的二进制值为1的最高位>=r,也就是8，则将temp_value看作NM,继续与G进行对齐模2运算
 *      直到temp_value的二进制值为1的最高位<r ,此时temp_value就是最终的校验值了
 *
 * @param data 单个字符校验
 * @return
 */
uint8_t genCRC_8(uint8_t data) {
    uint16_t G=0x107;
    //1。先计算NM的值
    uint32_t NM=data<<8;
//    printf("NM=%X\n",NM);
    //2.计算出data为1的最高位
    uint8_t index=getMbsBitIndex(data);
//    printf("index=%d\n",index);
    //3.G为1的最高位与NM为1的最高位对齐
    uint32_t tG=(G<<(index));
//    printf("tG=%X\n",tG);
    //4.对NM与tG进行异或运算
    uint32_t temp_value=NM^tG;
//    printf("temp_value=%X\n",temp_value);
    //取temp_value的[15:8]
    uint8_t tm=((temp_value&0xFF00)>>8);
    //5.获取temp_value的为1的最高位
    index=getMbsBitIndex(tm);
//    printf("index=%d\n",index);
    //一直循环到 index==0,并且temp_value的[15:8]==0
    while (index!=0||tm){
    //G为1的最高位与NM为1的最高位对齐
        tG=(G<<(index));
        //对temp_value与tG进行异或运算
        temp_value=temp_value^tG;
        tm=((temp_value&0xFF00)>>8);
        //获取temp_value的为1的最高位
        index=getMbsBitIndex(tm);
//        printf("while_index=%d\n",index);
    }
//    printf("temp_value=%X\n",temp_value);
    return temp_value;
}


uint8_t genCRC_temp(uint16_t data){
    uint16_t G=0x107;
    //1。先计算NM的值
    uint32_t NM=data;
//    printf("getCRC_temp_NM=%X\n",NM);
    //2.计算出data为1的最高位
    uint8_t index=getMbsBitIndex((data&0xFF00)>>8);
//    printf("index=%d\n",index);
    //3.G为1的最高位与NM为1的最高位对齐
    uint32_t tG=(G<<(index));
//    printf("tG=%X\n",tG);
    //4.对NM与tG进行异或运算
    uint32_t temp_value=NM^tG;
//    printf("temp_value=%X\n",temp_value);
    //取temp_value的[15:8]
    uint8_t tm=((temp_value&0xFF00)>>8);
    //5.获取temp_value的为1的最高位
    index=getMbsBitIndex(tm);
//    printf("index=%d\n",index);
    //一直循环到 index==0,并且temp_value的[15:8]==0
    while (index!=0||tm){
        //G为1的最高位与NM为1的最高位对齐
        tG=(G<<(index));
        //对temp_value与tG进行异或运算
        temp_value=temp_value^tG;
//        printf("temp_value=%X\n",temp_value);
        tm=((temp_value&0xFF00)>>8);
        //获取temp_value的为1的最高位
        index=getMbsBitIndex(tm);
//        printf("while_index=%d\n",index);
    }

//    printf("temp_value=%X\n",temp_value);
    return temp_value;
}


/**
 * 字符串校验
 * @param datas
 * @return
 */
uint8_t getStr_CRC_8_1(unsigned char * datas, uint16_t len){
    if(len==1){
        //如果只有一位元素，则直接校验一个字节的方法
       return genCRC_8(datas[0]);
    }

    //1。先计算NM的值 这个NM应该是所有字符二进制首尾相连最后再连接8个0
    //  先连接0号和1号两个元素NM，计算出NM/G 使用生成多项式模2运算
    //计算出临时的temp_crc,用这个temp_crc连接下一个元素作为新的NM
    //再次使用NM/G 使用生成多项式模2运算 计算出temp_crc
    //如此直到temp_crc连接的下一个元素未最后的一个元素，并计算出其temp_crc
    //最后将该temp_crc作为一个8位数据，计算出的CRC就是该字符串的校验值了
    //
    uint8_t index=0;
    uint16_t tempNM=datas[index]<<8|datas[++index];
//    printf("NM=%x\n",tempNM);

    //2.使用NM/G 使用生成多项式模2运算
    // 计算出这段的crc
    uint8_t temp_crc= genCRC_temp(tempNM);
//    printf("0temp_crc=%x\n",temp_crc);
    //3.计算到最后的两位连接在一起
    while (index<len-1){
        tempNM=(temp_crc<<8)|datas[++index];
        temp_crc= genCRC_temp(tempNM);
//        printf("temp_crc=%x\n",temp_crc);
    }
    uint8_t result= genCRC_8(temp_crc);
//    printf("result=%X\n",result);
    return result;
}

const uint8_t crc_table [256]={
        0x00,0x07,0x0E,0x09,0x1C,0x1B,0x12,0x15,
        0x38,0x3F,0x36,0x31,0x24,0x23,0x2A,0x2D,
        0x70,0x77,0x7E,0x79,0x6C,0x6B,0x62,0x65,
        0x48,0x4F,0x46,0x41,0x54,0x53,0x5A,0x5D,
        0xE0,0xE7,0xEE,0xE9,0xFC,0xFB,0xF2,0xF5,
        0xD8,0xDF,0xD6,0xD1,0xC4,0xC3,0xCA,0xCD,
        0x90,0x97,0x9E,0x99,0x8C,0x8B,0x82,0x85,
        0xA8,0xAF,0xA6,0xA1,0xB4,0xB3,0xBA,0xBD,
        0xC7,0xC0,0xC9,0xCE,0xDB,0xDC,0xD5,0xD2,
        0xFF,0xF8,0xF1,0xF6,0xE3,0xE4,0xED,0xEA,
        0xB7,0xB0,0xB9,0xBE,0xAB,0xAC,0xA5,0xA2,
        0x8F,0x88,0x81,0x86,0x93,0x94,0x9D,0x9A,
        0x27,0x20,0x29,0x2E,0x3B,0x3C,0x35,0x32,
        0x1F,0x18,0x11,0x16,0x03,0x04,0x0D,0x0A,
        0x57,0x50,0x59,0x5E,0x4B,0x4C,0x45,0x42,
        0x6F,0x68,0x61,0x66,0x73,0x74,0x7D,0x7A,
        0x89,0x8E,0x87,0x80,0x95,0x92,0x9B,0x9C,
        0xB1,0xB6,0xBF,0xB8,0xAD,0xAA,0xA3,0xA4,
        0xF9,0xFE,0xF7,0xF0,0xE5,0xE2,0xEB,0xEC,
        0xC1,0xC6,0xCF,0xC8,0xDD,0xDA,0xD3,0xD4,
        0x69,0x6E,0x67,0x60,0x75,0x72,0x7B,0x7C,
        0x51,0x56,0x5F,0x58,0x4D,0x4A,0x43,0x44,
        0x19,0x1E,0x17,0x10,0x05,0x02,0x0B,0x0C,
        0x21,0x26,0x2F,0x28,0x3D,0x3A,0x33,0x34,
        0x4E,0x49,0x40,0x47,0x52,0x55,0x5C,0x5B,
        0x76,0x71,0x78,0x7F,0x6A,0x6D,0x64,0x63,
        0x3E,0x39,0x30,0x37,0x22,0x25,0x2C,0x2B,
        0x06,0x01,0x08,0x0F,0x1A,0x1D,0x14,0x13,
        0xAE,0xA9,0xA0,0xA7,0xB2,0xB5,0xBC,0xBB,
        0x96,0x91,0x98,0x9F,0x8A,0x8D,0x84,0x83,
        0xDE,0xD9,0xD0,0xD7,0xC2,0xC5,0xCC,0xCB,
        0xE6,0xE1,0xE8,0xEF,0xFA,0xFD,0xF4,0xF3
};
const uint8_t crc_table_rohc [256]={
        0xCF,0x5E,0x2C,0xBD,0xC8,0x59,0x2B,0xBA,
        0xC1,0x50,0x22,0xB3,0xC6,0x57,0x25,0xB4,
        0xD3,0x42,0x30,0xA1,0xD4,0x45,0x37,0xA6,
        0xDD,0x4C,0x3E,0xAF,0xDA,0x4B,0x39,0xA8,
        0xF7,0x66,0x14,0x85,0xF0,0x61,0x13,0x82,
        0xF9,0x68,0x1A,0x8B,0xFE,0x6F,0x1D,0x8C,
        0xEB,0x7A,0x08,0x99,0xEC,0x7D,0x0F,0x9E,
        0xE5,0x74,0x06,0x97,0xE2,0x73,0x01,0x90,
        0xBF,0x2E,0x5C,0xCD,0xB8,0x29,0x5B,0xCA,
        0xB1,0x20,0x52,0xC3,0xB6,0x27,0x55,0xC4,
        0xA3,0x32,0x40,0xD1,0xA4,0x35,0x47,0xD6,
        0xAD,0x3C,0x4E,0xDF,0xAA,0x3B,0x49,0xD8,
        0x87,0x16,0x64,0xF5,0x80,0x11,0x63,0xF2,
        0x89,0x18,0x6A,0xFB,0x8E,0x1F,0x6D,0xFC,
        0x9B,0x0A,0x78,0xE9,0x9C,0x0D,0x7F,0xEE,
        0x95,0x04,0x76,0xE7,0x92,0x03,0x71,0xE0,
        0x2F,0xBE,0xCC,0x5D,0x28,0xB9,0xCB,0x5A,
        0x21,0xB0,0xC2,0x53,0x26,0xB7,0xC5,0x54,
        0x33,0xA2,0xD0,0x41,0x34,0xA5,0xD7,0x46,
        0x3D,0xAC,0xDE,0x4F,0x3A,0xAB,0xD9,0x48,
        0x17,0x86,0xF4,0x65,0x10,0x81,0xF3,0x62,
        0x19,0x88,0xFA,0x6B,0x1E,0x8F,0xFD,0x6C,
        0x0B,0x9A,0xE8,0x79,0x0C,0x9D,0xEF,0x7E,
        0x05,0x94,0xE6,0x77,0x02,0x93,0xE1,0x70,
        0x5F,0xCE,0xBC,0x2D,0x58,0xC9,0xBB,0x2A,
        0x51,0xC0,0xB2,0x23,0x56,0xC7,0xB5,0x24,
        0x43,0xD2,0xA0,0x31,0x44,0xD5,0xA7,0x36,
        0x4D,0xDC,0xAE,0x3F,0x4A,0xDB,0xA9,0x38,
        0x67,0xF6,0x84,0x15,0x60,0xF1,0x83,0x12,
        0x69,0xF8,0x8A,0x1B,0x6E,0xFF,0x8D,0x1C,
        0x7B,0xEA,0x98,0x09,0x7C,0xED,0x9F,0x0E,
        0x75,0xE4,0x96,0x07,0x72,0xE3,0x91,0x00
};
void crc_8_generTable(uint8_t crc_temp){
    printf("uint8_t crc_table [256]={\n");
    for (int i = 0; i <=255; ++i) {
        uint8_t crc= genCRC_8(i);
        if (crc==crc_temp){
            printf("================%d============",i);
        }
        if (i!=255){
            if((0xF0&crc)==0){
                printf("0x0%X,",crc);
            } else{
                printf("0x%X,",crc);
            }
        }else{
            if((0xF0&crc)==0){
                printf("0x0%X",crc);
            } else{
                printf("0x%X",crc);
            }
        }

       if ((i+1)%8==0){
           printf("\n");
       }

    }
    printf("};");
}


/**
 * 原理
 *     先将第一个数加入到temp_valule 这个8位内存中
 *     第一个循环是遍历所有数据-1个，因为最后一个数据需要在后面+8个0
 *     第二个内循环是加载完下一个数据
 *     1.判断内存的最高位是否为1，
 *      如果为1，左移1位，并将下一个数据的左移j位，并取最低位移入到内存的最低位
 *      并与G异或，将结果保存在内存中
 *      如果为0，左移1位，并将下一个数据的左移j位，并取最低位移入到内存的最低位
 *
 *      最后当所有数据都移入到内存中计算过之后，剩下的就是校验值了
 *
 * @param datas
 * @param len
 * @return
 */
uint8_t getStrCRC_8_2(unsigned char * datas, uint16_t len){
    uint8_t G=0x07;
    uint8_t temp_valule;
    temp_valule=datas[0];
    for (int i = 0; i < len-1; ++i) {
        for (int j = 7; j >=0; j--) {
            uint8_t tip=temp_valule&0x80;
            if (tip==0x80){
                //要移入的位
                uint8_t nextBit=(datas[i+1]>>j)&0x01;
                //左移1位，并将后面的一位移入内存中
                temp_valule=((temp_valule<<1)&0xFF)|nextBit;
                //并与G进行异或运算
                temp_valule=(temp_valule^G);
            }else{
                uint8_t nextBit=(datas[i+1]>>j)&0x01;
                //左移1位，并将后面的一位移入内存中
                temp_valule=((temp_valule<<1)&0xFF)|nextBit;
            }

        }
        printf("value=%X\n",temp_valule);

    }
    //最后一个的数据后面要加8个0
    temp_valule= gencrc8_2(temp_valule);
    printf("%X\n",temp_valule);
    return temp_valule;
}


/**
 * 原理
 *    G=0x07; 用CRC-8的16进制表示法 而不是用生成表达式的值0x107
 *    NM=data<<8;
 *    先将NM的高8位加载到8位长度的内存temp_value中r
 *
 *    如果内存中的最高位为1,将内存中的值左移一位，
 *    并将NM后面的位依次移入内存
 *    因为单个字节，后面全是8个0，左移自动补零相当于帮将NM后面的位自动移入该内存中了
 *    然后再与G进行异或并将结果保存在该内存中，这里的G=0x07,是因为这里将最高的1位移出，相当于除去了0x107的最高位
 *
 *    如果内存中的最高位为0,将内存中的值左移一位
 *    并将NM后面的位依次移入内存
 *    因为单个字节，后面全是8个0，左移自动补零相当于帮将NM后面的位自动移入该内存中了
 *
 *    直到NM的最低位也被加载到内存中,该内存中的值就是校验值
 *
 * @param data
 * @return
 */
uint8_t gencrc8_2(uint8_t data){
    uint8_t G=0x07;
    //这里可以直接用data加载到8位长度的内存中，之所以移位是对照公式的NM,便于理解
    uint16_t NM=data<<8;
    //把NM开头的8位加载到内存中
    uint8_t temp_value=(NM&0xFF00)>>8;

    //循环8次是为了将NM全部移动到8位内存中
    for (int i = 0; i <8; ++i) {
        //判断8位内存中的最高位是否是1
        uint8_t h=(temp_value&0x80);
        if(h==0x80){
            //如果是1，则左移1位，并与G进行异或，并保存在8位内存中
            temp_value=((temp_value<<1)&0xFF);
            temp_value=(temp_value^G);
        } else{
            //如果是0，则左移1位，不进行异或运算，并保存在8位内存中
            temp_value=((temp_value<<1)&0xFF);
        }
    }
//    printf("%X\n",temp_value);
    return temp_value;
}

uint8_t gencrc8_temp(uint16_t data){
    uint8_t G=0x07;
    //这里可以直接用data加载到8位长度的内存中，之所以移位是对照公式的NM
    uint16_t NM=data;
    //把NM开头的8位加载到内存中
    uint8_t temp_value=(NM>>8);

    //循环8次是为了将NM全部移动到8位内存中
    for (int i = 7; i >=0; i--) {
        //判断8位内存中的最高位是否是1
        uint8_t h=(temp_value&0x80);
        if(h==0x80){
            //如果是1，则左移1位，并与G进行异或，并保存在8位内存中
            temp_value=((temp_value<<1)&0xFF)|((NM>>i)&0x01);
            temp_value=(temp_value^G);
        } else{
            //如果是0，则左移1位，不进行异或运算，并保存在8位内存中
            temp_value=((temp_value<<1)&0xFF)|((NM>>i)&0x01);
        }
    }
//    printf("%X\n",temp_value);
    return temp_value;
}


/**
 * /**
 * 查表法计算 crc
 *  生成多项式：x^8+x^2+x+1
 *  16进制表示：0x07
 *  初始值：0x00
 *  输入输出反转：False
 *
 *
 * 该查表法原理
 *      以  E9AAEE为例
 *          先计算E9的crc值===>91
 *          先算E9AA =>gencrc8_temp(0xE9AA)==>3B
 *          恰好相当于E9的crc值异或AA:gencrc8_temp(0xE9)^AA==>3B
 *          接着以3B作为EE的高8位计算getcrc8_temp(3BEE)===>4F
 *          恰好相当于3B的crc值异或EE:gencrc8_temp(0x3B)^AA==>4F
 *          最后计算4F的crc gencrc8_temp(0x4F)===>EA 这个值机最终的CRC值
 *
 *          数学原理
 *          NM=M*X^r
 *          E900=E9*X^8==>
 *                      (X^7+X6+X^5+X^3+1)*X8=X^15+X^14+x^13+X^11+^X8
 *          由因为求E9的校验值，其实就是求E900/G 的余数CRC1
 *          有因为只算高8位，所以E900/G和E9AA/G的商是相等的
 *          设E9为K,AA为L，K/G和AA/G的商为N
 *          E900=K*X^8
 *          GN+CRC1=K*X^8
 *          E9AA=K*X^8+L
 *          GN+CRC2=K*X^8+L
 *          K*X^8-CRC1=K*X^8+L-CRC2
 *          CRC2=K*X^8+L-K*X^8+CRC1
 *              =L+CRC1
 *         由因为模2运算的加减法相当于异或运算
 *         所以CRC2=CRC1^L
 *         E9AA的校验值CRC2相当于E900的CRC1^AA
 *
 *
            对应的多项式为 x^8+x^2+x+1===>0x107==>对应的二进制是==>100000111
 * @param datas
 * @param len
 * @return
 */

uint8_t crc8(unsigned char * datas, uint16_t len) {
    uint8_t crc=0;
    for (int i = 0; i < len; ++i) {
            crc=(crc_table[crc]^datas[i]);
//            printf("table[%d]=%X  crc=%X\n",i,datas[i],crc);
    }
    return crc_table[crc];
}

/**
 * 获取CRC/ITU的校验值
 *  生成多项式：x^8+x^2+x+1
    16进制表示：0x07
    初始值：0x00
    结果异或值：0x55
    输入输出反转：False
 * @param datas
 * @param len
 * @return
 */
uint8_t crc8_ITU(unsigned char * datas, uint16_t len){
    return crc8(datas, len) ^ 0x55;
}
/**
 *      对应的多项式是x^8+x^2+x+1
 *       对应多项式16进制 0x07
 *       输入输出反转：true  :因为是先传送低位
 *       初始值：FF  crc的初值值
 *
 *       计算原理
 *       1.将data按位取反，即data^0xFF
 *       2.取反后data放入一个8位的内存中，
 *       如果最低位为1，右移一位，并异或0x07的翻转值0xE0（高位变低位，低位变高位）
 *       如果不为1，只右移一位
 *       如此，直到8位数据全部计算完毕
 *
 * @param data
 * @param len
 * @return
 */
uint8_t crc8_ROHC_char(unsigned char data){

    uint8_t crc_value=0xFF;

    //将数据按位取反
    crc_value=crc_value^data;
    for (int i = 0; i < 8; ++i) {
        //查看最低位是否为1
        if(crc_value&0x01==0x01){
            crc_value= (crc_value>>1)^0xE0;
        } else{
            crc_value=crc_value>>1;
        }
    }

//    printf("%x\n",crc_value);
    return crc_value;

}
uint8_t getcrc8_rohc_temp(uint16_t data){
    uint8_t crc_value=0xFF;
    uint8_t data_second=(data&0xFF)^0xFF;
    //将数据按位取反
    crc_value=crc_value^((data>>8)&0xFF);
    for (int i = 0; i < 8; ++i) {
        //查看最低位是否为1,移位补data_second的低位
        if(crc_value&0x01==0x01){
            crc_value= ((crc_value>>1)|((data_second>>i)<<7))^0xE0;
        } else{
            crc_value=((crc_value>>1)|((data_second>>i)<<7));
        }

    }
    printf("temp=========%x\n",crc_value);
    return crc_value;
}

uint8_t getcrc8_rohc_2(unsigned char *datas , uint8_t len){
    uint8_t crc_value=datas[0];
    //将数据按位取反
    for (int i = 0; i < len-1; ++i) {
        crc_value=crc_value^0xFF;
        for (int j = 0; j < 8; ++j) {
            //查看最低位是否为1,移位补data_second的低位
            if(crc_value&0x01==0x01){
                crc_value= ((crc_value>>1)|(((datas[i+1]^0xFF)>>j)<<7))^0xE0;
            } else{
                crc_value=((crc_value>>1)|(((datas[i+1]^0xFF)>>j)<<7));
            }
        }
        printf("=====================================%X\n",crc_value);
    }

    crc_value= crc8_ROHC_char(crc_value);

    printf("====%X\n",crc_value);
    return crc_value;
}
/**
 * 查表法原理
 *      1.开头第一个char的crc异或 下一个char的再异或0xFF即是这两个中间值的crc
 *      并将这个中间值得crc作为第一步的开头的crc 重复此步骤
 *      2.再取最后一个crc得crc值
 *
 *
 *  生成表达式：x8 + x2 + x + 1
 *  16进制表示法：0x07
 *  初始值：0xFF
 *  输入输出反转：true
 * @param datas
 * @param len
 * @return
 */
uint8_t crc8_ROHC(unsigned char *datas , uint8_t len){
    uint8_t crc=datas[0];
    for (int i = 0; i < len-1; ++i) {
        crc=crc_table_rohc[crc]^datas[i+1]^0xFF;
//        printf("===%X\n",crc);
//            printf("table[%d]=%X  crc=%X\n",i,datas[i],crc);
    }
    return crc_table_rohc[crc];
}



/**
 * 生成中间表
 */
void crc_8_generTable_ROHC(){
    printf("uint8_t crc_table_rohc [256]={\n");
    for (int i = 0; i <=255; ++i) {
        uint8_t crc= crc8_ROHC_char(i);
        if (i!=255){
            if((0xF0&crc)==0){
                printf("0x0%X,",crc);
            } else{
                printf("0x%X,",crc);
            }
        }else{
            if((0xF0&crc)==0){
                printf("0x0%X",crc);
            } else{
                printf("0x%X",crc);
            }
        }

        if ((i+1)%8==0){
            printf("\n");
        }

    }
    printf("};");
}


/**
 * 生成多项式：
 *      x8 + x5 + x4 + 1
 * 16进制表示：0x31
 * 初始值：0x00
 * 结果异或值：0x00
 * 输入输出反转:true
 * @param datas
 * @param len
 * @return
 */
uint8_t gencrc8_MAXIM(unsigned char data){
    uint8_t crc_value=data;
    for (int i = 0; i < 8; ++i) {
        //查看最低位是否为1
        if(crc_value&0x01==0x01){
            crc_value= (crc_value>>1)^0x8C;
        } else{
            crc_value=crc_value>>1;
        }
    }

//    printf("%x\n",crc_value);
    return crc_value;
}

void crc_8_generTable_MAXIM(){
    printf("uint8_t crc_table_maxim [256]={\n");
    for (int i = 0; i <=255; ++i) {
        uint8_t crc= gencrc8_MAXIM(i);
        if (i!=255){
            if((0xF0&crc)==0){
                printf("0x0%X,",crc);
            } else{
                printf("0x%X,",crc);
            }
        }else{
            if((0xF0&crc)==0){
                printf("0x0%X",crc);
            } else{
                printf("0x%X",crc);
            }
        }

        if ((i+1)%8==0){
            printf("\n");
        }

    }
    printf("};");
}
const uint8_t crc_table_maxim [256]={
        0x00,0x5E,0xBC,0xE2,0x61,0x3F,0xDD,0x83,
        0xC2,0x9C,0x7E,0x20,0xA3,0xFD,0x1F,0x41,
        0x9D,0xC3,0x21,0x7F,0xFC,0xA2,0x40,0x1E,
        0x5F,0x01,0xE3,0xBD,0x3E,0x60,0x82,0xDC,
        0x23,0x7D,0x9F,0xC1,0x42,0x1C,0xFE,0xA0,
        0xE1,0xBF,0x5D,0x03,0x80,0xDE,0x3C,0x62,
        0xBE,0xE0,0x02,0x5C,0xDF,0x81,0x63,0x3D,
        0x7C,0x22,0xC0,0x9E,0x1D,0x43,0xA1,0xFF,
        0x46,0x18,0xFA,0xA4,0x27,0x79,0x9B,0xC5,
        0x84,0xDA,0x38,0x66,0xE5,0xBB,0x59,0x07,
        0xDB,0x85,0x67,0x39,0xBA,0xE4,0x06,0x58,
        0x19,0x47,0xA5,0xFB,0x78,0x26,0xC4,0x9A,
        0x65,0x3B,0xD9,0x87,0x04,0x5A,0xB8,0xE6,
        0xA7,0xF9,0x1B,0x45,0xC6,0x98,0x7A,0x24,
        0xF8,0xA6,0x44,0x1A,0x99,0xC7,0x25,0x7B,
        0x3A,0x64,0x86,0xD8,0x5B,0x05,0xE7,0xB9,
        0x8C,0xD2,0x30,0x6E,0xED,0xB3,0x51,0x0F,
        0x4E,0x10,0xF2,0xAC,0x2F,0x71,0x93,0xCD,
        0x11,0x4F,0xAD,0xF3,0x70,0x2E,0xCC,0x92,
        0xD3,0x8D,0x6F,0x31,0xB2,0xEC,0x0E,0x50,
        0xAF,0xF1,0x13,0x4D,0xCE,0x90,0x72,0x2C,
        0x6D,0x33,0xD1,0x8F,0x0C,0x52,0xB0,0xEE,
        0x32,0x6C,0x8E,0xD0,0x53,0x0D,0xEF,0xB1,
        0xF0,0xAE,0x4C,0x12,0x91,0xCF,0x2D,0x73,
        0xCA,0x94,0x76,0x28,0xAB,0xF5,0x17,0x49,
        0x08,0x56,0xB4,0xEA,0x69,0x37,0xD5,0x8B,
        0x57,0x09,0xEB,0xB5,0x36,0x68,0x8A,0xD4,
        0x95,0xCB,0x29,0x77,0xF4,0xAA,0x48,0x16,
        0xE9,0xB7,0x55,0x0B,0x88,0xD6,0x34,0x6A,
        0x2B,0x75,0x97,0xC9,0x4A,0x14,0xF6,0xA8,
        0x74,0x2A,0xC8,0x96,0x15,0x4B,0xA9,0xF7,
        0xB6,0xE8,0x0A,0x54,0xD7,0x89,0x6B,0x35
};

uint8_t crc8_MAXIM(unsigned char * datas, uint8_t len){
    uint8_t crc=0x00;
    for (int i = 0; i < len; ++i) {
        crc=(crc_table_maxim[crc]^datas[i]);
    }
    return crc_table_maxim[crc];
}
uint8_t gencrc8_maxim_temp(uint16_t data){
    uint8_t crc_value=(data>>8);
    uint8_t scond=data&0xFF;
    for (int j = 0; j < 8; ++j) {
        //查看最低位是否为1
        if(crc_value&0x01==0x01){
            crc_value= ((crc_value>>1)|((scond>>j&0x01)<<7))^0x8C;
        } else{
            crc_value=(crc_value>>1)|((scond>>j&0x01)<<7);
        }
        printf("^^^^%X\n",crc_value);
    }
    printf("^^^^^^^^^^^%X\n",crc_value);
}

uint8_t getcrc8_maxim(unsigned char * datas, uint8_t len){
    uint8_t crc_value=datas[0];
    for (int i = 0; i < len-1; ++i) {
        for (int j = 0; j < 8; ++j) {
            //查看最低位是否为1
            if(crc_value&0x01==0x01){
                crc_value= ((crc_value>>1)|((datas[i+1]>>j&0x01)<<7))^0x8C;
            } else{
                crc_value=(crc_value>>1)|((datas[i+1]>>j&0x01)<<7);
            }
        }
        printf("==============%X\n",crc_value);
    }
    crc_value=crc_table_maxim[crc_value];
    printf("%X\n",crc_value);
    return crc_value;
}

